package com.dctp.ems.controller;

import com.alibaba.fastjson.JSON;
import com.dctp.common.cache.QrSessionCache;
import com.dctp.common.cache.UserCache;
import com.dctp.common.controller.BaseController;
import com.dctp.common.db.RoleDb;
import com.dctp.common.utils.*;
import com.dctp.common.vo.JsonResult;
import com.dctp.common.vo.PageResult;
import com.jfinal.aop.Before;
import com.jfinal.aop.Clear;
import com.jfinal.core.Path;
import com.jfinal.kit.Kv;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Record;
import com.jfinal.plugin.activerecord.tx.Tx;

import java.util.*;
import java.util.stream.Collectors;

/**
 * EMS 管理员接口
 *
 * basePath: /admin
 */
@Path("/admin")
public class EmsAdminController extends BaseController {


    @Clear
    public void qrInit() {

        String qrId = UUIDUtil.random32();
        // 1) 缓存会话状态：PENDING，TTL 120s（演示用内存；生产请用 Redis 设置过期）
        QrSessionCache.putPending(qrId, 120);

        // 2) 二维码内容：仅承载 qrId（小程序扫码后拿到 qrId）
        String content = "EMS_LOGIN:" + qrId;

        // 3) 生成 PNG data URL
        String dataUrl;
        try {
            dataUrl = QrCodeUtil.toDataUrlPng(content, 220, 220);
        } catch (Exception e) {
            renderJson(JsonResult.failWithMessage("生成二维码失败"));
            return;
        }

        renderJson(JsonResult.successWithData(Kv.by("qrId", qrId).set("qrImage", dataUrl)));
    }

    public void info() {
        Record admin = getRequestUser();
        renderJson(JsonResult.successWithData(admin.getColumns()));
    }

    /** 请求中取管理员 ID：优先 path，其次登录拦截器注入的 reqUser */
    private Long getPathOrReqAdminId() {
        String idStr = getPara(0);
        if (StrKit.notBlank(idStr) && idStr.matches("\\d+")) return Long.valueOf(idStr);
        return getUserId();
    }

    public void list() {

        int page     = getInt("currentPage", 1);
        int pageSize = getInt("pageSize", 10);
        String login = getPara("login_account", "");
        String phone = getPara("phone", "");
        String status = getPara("status", "");

        StringBuilder where = new StringBuilder(" WHERE a.is_hidden=0 ");
        List<Object> params = new ArrayList<>();
        if (StrKit.notBlank(login)) {
            where.append("AND a.login_account LIKE ? ");
            params.add('%' + login + '%');
        }
        if (StrKit.notBlank(phone)) {
            where.append("AND a.phone LIKE ? ");
            params.add('%' + phone + '%');
        }
        if (StrKit.notBlank(status)) {
            where.append("AND a.status = ? ");
            params.add(status);
        }

        String sqlSelect = "SELECT a.*,b.role_id  ";
        String sqlExcept = "FROM card_enterprise_admin a left join card_enterprise_admin_role b on a.id = b.admin_id " + where + " ORDER BY a.id DESC ";
        var p = Db.paginate(page, pageSize, sqlSelect, sqlExcept, params.toArray());
        Map<Long, String> roleMap = Db.find("select id,name from card_enterprise_role")
                .stream()
                .collect(Collectors.toMap(
                        item -> item.getLong("id"),      // key
                        item -> item.getStr("name")      // value
                ));
        if (CollectUtil.isNotEmpty(p.getList())) {
            for (Record record : p.getList()) {
                Long roleId = record.getLong("role_id");
                if (null != roleId) {
                    record.set("role_name", roleMap.get(roleId));
                }
                record.set("user", UserCache.getBasic(record.getLong("user_id")));
            }
        }
        renderJson(JsonResult.successWithData(
            new PageResult<>(p.getList(), p.getTotalRow(), pageSize, page)
        ));
    }
    @Clear
    public void login() {

        Record body = jsonBody();
        String login_acct = body.getStr("login_account");
        String pwd = body.getStr("password");
        if (StrKit.isBlank(login_acct) || StrKit.isBlank(pwd)) {
            renderJson(JsonResult.failWithMessage("参数缺失"));
            return;
        }

        Record admin = Db.findFirst(
                "SELECT * FROM card_enterprise_admin WHERE login_account=? AND password=?",
                login_acct, pwd);
        if (admin == null) {
            renderJson(JsonResult.failWithMessage("账号或密码错误"));
            return;
        }

        List<Integer> roleIds = Db.query("SELECT role_id FROM card_enterprise_admin_role WHERE admin_id=?",
                admin.getLong("id"));
        List<String> roles = roleIds.isEmpty() ? List.of() :
                Db.find("SELECT id, role FROM card_enterprise_role").stream()
                        .filter(r -> roleIds.contains(r.getInt("id")))
                        .map(r -> StrKit.notBlank(r.getStr("role")) ? r.getStr("role") : r.getInt("id").toString())
                        .collect(Collectors.toList());

        Record data = new Record();
        data.set("accessToken", admin.getStr("token"))
            .set("refreshToken", admin.getStr("token"))
            .set("expires", System.currentTimeMillis() + 7L * 24 * 3600 * 1000)
            .set("avatar", admin.getStr("avatar"))
            .set("username", admin.getStr("login_account"))
            .set("nickname", getStr(admin, "nickname", admin.getStr("login_account")))
            .set("roles", roles)
            .set("permissions", List.of());

        data.set("id", admin.getLong("id"));
        data.set("role_field",getFilterField(admin));
        renderJson(JsonResult.successWithData(data.getColumns()));
    }


    @Before(Tx.class)
    public void update() {

        Long id = getParaToLong(0);
        Record body = jsonBody();
        if (id == null) {
            renderJson(JsonResult.failWithMessage("参数缺失"));
            return;
        }

        String roles = body.get( "roles", "");
        body.set("id", id);
        body.remove("roles");
        if (body.toMap().keySet().size() > 1) {
            boolean result = Db.update("card_enterprise_admin", body);
            if (!result) {
                throw new RuntimeException("更新管理员信息失败");
            }
        }
        if (StringUtil.isNotEmpty(roles)) {
            Db.update("DELETE FROM card_enterprise_admin_role WHERE admin_id=?", id);
            for (String roleId : roles.split(",")) {
                Db.save("card_enterprise_admin_role",
                        new Record().set("admin_id", id).set("role_id", roleId));
            }
        }
        renderJson(JsonResult.success());
    }


    @Before(Tx.class)
    public void delete() {
        Long id = getParaToLong(0);
        if (id == null) {
            renderJson(JsonResult.failWithMessage("参数缺失"));
            return;
        }
        int r = Db.update("DELETE FROM card_enterprise_admin WHERE id=?", id);
        if (r == 0) {
            throw new RuntimeException("删除管理员失败，可能不存在");
        }
        Db.update("DELETE FROM card_enterprise_admin_role WHERE admin_id=?", id);
        renderJson(JsonResult.success());
    }

    @Before(Tx.class)
    public void deleteMulti() {
        Record body = jsonBody();
        List<Integer> ids = body.get("ids", Collections.emptyList());
        if (ids.isEmpty()) {
            renderJson(JsonResult.failWithMessage("ids 不能为空"));
            return;
        }
        String inSql = ids.stream().map(x -> "?").collect(Collectors.joining(","));
        Db.update("DELETE FROM card_enterprise_admin WHERE id IN (" + inSql + ")", ids.toArray());
        Db.update("DELETE FROM card_enterprise_admin_role WHERE admin_id IN (" + inSql + ")", ids.toArray());
        renderJson(JsonResult.success());
    }


    public void menu() {
        Long adminId = getPathOrReqAdminId();
        if (adminId == null) {
            renderJson(JsonResult.failWithMessage("参数缺失"));
            return;
        }
        List<Record> routes = buildMenuRoutes(adminId);
        renderJson(JsonResult.successWithData(routes));
    }

    public void roles() {
        Long adminId = getPathOrReqAdminId();
        if (adminId == null) {
            renderJson(JsonResult.failWithMessage("参数缺失"));
            return;
        }

        // 1. 查询角色ID列表（统一为 Long 类型）
        List<Long> roleIds = Db.find("SELECT role_id FROM card_enterprise_admin_role WHERE admin_id=?", adminId)
                .stream()
                .filter(Objects::nonNull)
                .map(r->r.getLong("role_id"))  // 确保都是 Long
                .distinct()              // 去重
                .toList();

        if (roleIds.isEmpty()) {
            renderJson(JsonResult.successWithData(List.of()));
            return;
        }

        // 2. 查询所有角色
        List<Record> roles = Db.find("SELECT * FROM card_enterprise_role");

        // 3. 过滤角色，只保留 admin 拥有的
        roles.removeIf(r -> r.get("id") == null || !roleIds.contains(((Number) r.get("id")).longValue()));

        renderJson(JsonResult.successWithData(roles));
    }



    private List<Record> buildMenuRoutes(Long adminId) {
        List<Long> roleIds = Db.query("SELECT role_id FROM card_enterprise_admin_role WHERE admin_id=?", adminId);
        if (roleIds.isEmpty()) return List.of();

        String inRole = roleIds.stream().map(x -> "?").collect(Collectors.joining(","));
        List<Long> menuIds = Db.query("SELECT menu_id FROM card_enterprise_role_menu WHERE role_id IN (" + inRole + ")", roleIds.toArray());
        if (menuIds.isEmpty()) return List.of();

        List<Record> allMenus = Db.find("SELECT * FROM card_enterprise_menu");
        List<Record> owned = allMenus.stream()
                .filter(m -> menuIds.contains(m.getLong("id")))
                .collect(Collectors.toList());

        return buildRouteTree(owned, 0);
    }

    private List<Record> buildRouteTree(List<Record> list, int parentId) {
        List<Record> routes = new ArrayList<>();

        for (Record m : list) {
            Integer pid = m.getInt("parent_id");
            if ((pid == null ? 0 : pid) == parentId) {
                Integer menuType = m.getInt("menu_type");

                // === 处理目录/菜单 ===
                if (menuType != null && menuType != 3) {
                    Kv meta = Kv.create()
                            .set("title", m.getStr("title"))
                            .set("icon", m.getStr("icon"))
                            .set("rank", m.getInt("rank"))
                            .set("keepAlive", m.getBoolean("keep_alive"));

                    Record r = new Record()
                            .set("path", m.getStr("path"))
                            .set("component", m.getStr("component"))
                            .set("name", m.getStr("name"))
                            .set("meta", meta);

                    // children: 递归（菜单和按钮都会返回）
                    List<Record> children = buildRouteTree(list, m.getInt("id"));

                    // 过滤掉子菜单里的按钮，按钮要挂到 auths
                    List<Record> childMenus = new ArrayList<>();
                    List<String> auths = new ArrayList<>();

                    for (Record child : children) {
                        Integer childType = child.getInt("menu_type");
                        if (childType != null && childType == 3) {
                            // 按钮 → 加到 auths
                            if (child.getStr("auths") != null) {
                                auths.add(child.getStr("auths"));
                            }
                        } else {
                            childMenus.add(child);
                        }
                    }

                    if (!childMenus.isEmpty()) {
                        r.set("children", childMenus);
                    }
                    if (!auths.isEmpty()) {
                        meta.set("auths", auths);
                    }

                    routes.add(r);
                }

                // === 如果是按钮，直接返回原始数据（供父节点收集）===
                else if (menuType != null && menuType == 3) {
                    routes.add(m);
                }
            }
        }

        // 排序
        routes.sort(Comparator.comparing(
                rec -> {
                    Integer menuType = rec.getInt("menu_type");
                    if (menuType != null && menuType == 3) {
                        // 按钮不参与排序，放最后
                        return Integer.MAX_VALUE;
                    }
                    Kv meta = rec.get("meta");
                    if (meta != null) {
                        Integer rank = meta.getInt("rank");
                        return rank == null ? Integer.MAX_VALUE : rank;
                    }
                    return Integer.MAX_VALUE;
                }
        ));

        return routes;
    }
}
